package es.cazadoresmadridejos.common.bean.dao.impl;

import java.sql.SQLException;
import java.util.List;

import javax.persistence.Entity;

import org.displaytag.properties.SortOrderEnum;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import es.cazadoresmadridejos.common.bean.dao.Dao;
import es.cazadoresmadridejos.model.BaseEntity;
import es.cazadoresmadridejos.objs.web.Page;

@SuppressWarnings("unchecked")
public abstract class DaoImpl<T extends BaseEntity> extends HibernateDaoSupport implements Dao<T> {
	@Autowired
	public void init(SessionFactory factory) {
		setSessionFactory(factory);
	}


	public abstract T newInstance();

	public String getEntityName(){
		return newInstance().getClass().getAnnotation(Entity.class).name();
	}

	@Override
	public T get(final Long id) {
		return (T) getHibernateTemplate().execute(new HibernateCallback() {
			@Override
			public Object doInHibernate(Session session) throws HibernateException,
			SQLException {
				StringBuilder hql = new StringBuilder();
				hql
				.append("select obj ")
				.append(" from ")
				.append(getEntityName())
				.append(" obj ")
				.append(" where obj.id = :id");

				Query query = session.createQuery(hql.toString());
				query.setLong("id", id);

				return query.uniqueResult();
			}
		});
	}

	public Long save(T entity) {
		getHibernateTemplate().saveOrUpdate(entity);
		return entity.getId();
	};

	@Override
	public List<T> findAll() {
		return (List<T>) getHibernateTemplate().execute(new HibernateCallback() {
			
			@Override
			public Object doInHibernate(Session session) throws HibernateException,
					SQLException {
				StringBuilder hql = new StringBuilder();
				hql.append("select t ");
				hql.append(" from ");
				hql.append(getEntityName());
				hql.append(" t ");

				Query query = session.createQuery(hql.toString());
				
				return query.list();
			}
		});
	}
	
	protected String getSort(Page page, String prefix){
		return " order by " + prefix + "." + page.getSort() + " " + (page.getSortOrder().equals(SortOrderEnum.ASCENDING)?"asc":"desc");
	}
	
	@Override
	public void delete(final Long id) {
		getHibernateTemplate().execute(new HibernateCallback() {
			
			@Override
			public Object doInHibernate(Session session) throws HibernateException,
					SQLException {
				
				StringBuilder hql = new StringBuilder();
				hql
				.append("delete from ")
				.append(getEntityName())
				.append(" where id = :id ");
				
				Query query = session.createQuery(hql.toString());
				query.setParameter("id", id);
				
				return query.executeUpdate();
			}
		});
	}
	
	@Override
	public void disable(final Long id) {
		getHibernateTemplate().execute(new HibernateCallback() {
			
			@Override
			public Object doInHibernate(Session session) throws HibernateException,
			SQLException {
				
				StringBuilder hql = new StringBuilder();
				hql
				.append("update ")
				.append(getEntityName())
				.append(" set active = 'INACTIVE' ")
				.append(" where id = :id ");
				
				Query query = session.createQuery(hql.toString());
				query.setParameter("id", id);
				
				return query.executeUpdate();
			}
		});
	}
	
	protected void hqlList(StringBuilder hql, StringBuilder hqlCount, String query){
		hql.append(query);
		hqlCount.append(query);
	}
}
